using UnityEngine;
using System.Collections;

/// \class  gkCylindricalPosition
/// \brief 	Cylindrical position
[AddComponentMenu("GK/Engine/Core/Transform/gkCylindricalPosition")]
public class gkCylindricalPosition : MonoBehaviour
{
	/// Are we only using the cylindrical position => optimisation
	/// avoid back and forth convertion between cylindrical and cartesian coordinates
	public bool OnlyUseCylindricalPosition = true;
	
	/// Is the component started
	private bool m_bInitializedCylindricalPositionWithCartesian;
	
	/// The cylindrical coordinates 
	//  use a Vector3 for simplicity sake
	//  (x, y, z) = (r, theta, z)
	private Vector3 m_f3Position;
	public Vector3 position
	{
		get
		{
			if(OnlyUseCylindricalPosition == false || m_bInitializedCylindricalPositionWithCartesian == false)
			{
				// Todo_Sev : check the perf of convertion back and forth convertion
				ConvertCartesianToCylindrical();
			}
			return m_f3Position;
		}
		
		set
		{
			m_f3Position = value;
			
			// We ensure thet theta is in [ 0.0f, 360.0f[
			m_f3Position.y = Mathf.Repeat(m_f3Position.y, 360.0f); 
			
			// We convert the cylindrical position in cartesian
			ConvertCylindricalToCartesian();
		}
	}
	
	/// \brief  Called just before the first update
	void Start() 
	{
		ConvertCartesianToCylindrical();
	}
	
	/// \brief  Update the transform, convert the cylindrical position
	///  in cartesian position
	void ConvertCylindricalToCartesian()
	{
		Vector3 f3CartesianPosition;
		
		// Convert the cylindrical position in cartesian coordinates
		f3CartesianPosition.x = m_f3Position.x * Mathf.Cos(m_f3Position.y * Mathf.Deg2Rad);
		f3CartesianPosition.y = m_f3Position.x * Mathf.Sin(m_f3Position.y * Mathf.Deg2Rad);
		f3CartesianPosition.z = m_f3Position.z;
		
		// Set the transform position to the convert coordinate
		transform.position = f3CartesianPosition;
	}
	
	/// \brief  Update the cylindrical position, convert the cylindrical position
	///  in cartesian position
	void ConvertCartesianToCylindrical()
	{
		Vector3 f3CartesianPosition;
		
		// Get the cartesian position from the transform
		f3CartesianPosition = transform.position;
		
		// Convert the cartesian position in cylindrical coordinates
		m_f3Position.x = Mathf.Sqrt(f3CartesianPosition.x * f3CartesianPosition.x + f3CartesianPosition.y * f3CartesianPosition.y);
		
		// If r=0 theta can be any angle
		// for the temporal continuity sake we doesn't modify it if r=0
		// else we compute theta based on the cartesian coordinate
		if(m_f3Position.x != 0)
		{
			m_f3Position.y = Mathf.Rad2Deg * Mathf.Atan2(f3CartesianPosition.y, f3CartesianPosition.x);
		}
		m_f3Position.z = f3CartesianPosition.z;
		
		m_bInitializedCylindricalPositionWithCartesian = true;
	}	
}